package commands

import (
	"context"
	"fmt"
	"strconv"

	"github.com/spf13/cobra"
	"github.com/yourusername/virt-manager-go/internal/models"
)

// NewDomainCommand 创建虚拟机管理命令
func NewDomainCommand() *cobra.Command {
	cmd := &cobra.Command{
		Use:     "domain",
		Short:   "虚拟机管理",
		Long:    "管理虚拟机（域）的生命周期",
		Aliases: []string{"vm", "d"},
	}

	cmd.AddCommand(newDomainListCommand())
	cmd.AddCommand(newDomainGetCommand())
	cmd.AddCommand(newDomainCreateCommand())
	cmd.AddCommand(newDomainDeleteCommand())
	cmd.AddCommand(newDomainStartCommand())
	cmd.AddCommand(newDomainShutdownCommand())
	cmd.AddCommand(newDomainRebootCommand())
	cmd.AddCommand(newDomainForceStopCommand())
	cmd.AddCommand(newDomainSuspendCommand())
	cmd.AddCommand(newDomainResumeCommand())
	cmd.AddCommand(newDomainVCPUsCommand())
	cmd.AddCommand(newDomainMemoryCommand())
	cmd.AddCommand(newDomainXMLCommand())
	cmd.AddCommand(newDomainStatsCommand())
	cmd.AddCommand(newDomainStatusCommand())

	return cmd
}

func newDomainListCommand() *cobra.Command {
	var (
		outputFormat string
		connectionID string
	)

	cmd := &cobra.Command{
		Use:     "list",
		Short:   "列出所有虚拟机",
		Aliases: []string{"ls"},
		RunE: func(cmd *cobra.Command, args []string) error {
			client := ClientManager.GetClient(cmd.Flag("server").Value.String())

			var domains []models.DomainSummary
			var err error

			domains, err = client.Domain().ListDomains(context.Background(), connectionID)
			if err != nil {
				return fmt.Errorf("列出虚拟机失败: %w", err)
			}

			return printOutput(domains, outputFormat)
		},
	}

	cmd.Flags().StringVarP(&outputFormat, "output", "o", "table", "输出格式 (table, json, yaml)")
	cmd.Flags().StringVarP(&connectionID, "connection", "c", "", "连接 ID")
	return cmd
}

func newDomainGetCommand() *cobra.Command {
	var (
		outputFormat string
		connectionID string
	)

	cmd := &cobra.Command{
		Use:   "get [name]",
		Short: "获取虚拟机详情",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			client := ClientManager.GetClient(cmd.Flag("server").Value.String())

			var domain *models.DomainDetail
			var err error

			domain, err = client.Domain().GetDomain(context.Background(), connectionID, args[0])
			if err != nil {
				return fmt.Errorf("获取虚拟机详情失败: %w", err)
			}

			return printOutput(domain, outputFormat)
		},
	}

	cmd.Flags().StringVarP(&outputFormat, "output", "o", "table", "输出格式 (table, json, yaml)")
	cmd.Flags().StringVarP(&connectionID, "connection", "c", "", "连接 ID")
	return cmd
}

func newDomainCreateCommand() *cobra.Command {
	var (
		vcpus        uint
		memory       uint64
		connectionID string
		diskPath     string
		diskBus      string
		architecture string
		bootMode     string
		networkMode  string
		networkName  string
		osVariant    string
		autoStart    bool
		secureBoot   bool

		// CDROM 配置
		cdromPath string
		cdromBus  string
		cdromBoot bool
	)

	cmd := &cobra.Command{
		Use:   "create [name]",
		Short: "创建新虚拟机",
		Long: `创建新虚拟机，支持多种配置选项。

示例:
  # 创建基础虚拟机
  vmctl domain create my-vm --disk-path /var/lib/libvirt/images/my-vm.qcow2

  # 创建带 CDROM 的虚拟机
  vmctl domain create my-vm --disk-path /var/lib/libvirt/images/my-vm.qcow2 \
    --cdrom-path /var/lib/libvirt/images/ubuntu.iso --cdrom-boot

  # 创建完整配置的虚拟机
  vmctl domain create my-vm --disk-path /var/lib/libvirt/images/my-vm.qcow2 \
    --vcpus 4 --memory 4096 --architecture x86_64 --boot-mode uefi \
    --cdrom-path /var/lib/libvirt/images/ubuntu.iso --cdrom-boot`,
		Args: cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			client := ClientManager.GetClient(cmd.Flag("server").Value.String())

			// 验证必填参数
			if diskPath == "" {
				return fmt.Errorf("磁盘路径是必需的，请使用 --disk-path 参数")
			}

			req := &models.CreateDomainRequest{
				Name:         args[0],
				VCPUs:        vcpus,
				Memory:       uint(memory),
				DiskPath:     diskPath,
				DiskBus:      diskBus,
				Architecture: architecture,
				BootMode:     bootMode,
				NetworkMode:  networkMode,
				NetworkName:  networkName,
				OSVariant:    osVariant,
				AutoStart:    autoStart,
				SecureBoot:   secureBoot,

				// CDROM 配置
				CDROMPath: cdromPath,
				CDROMBus:  cdromBus,
				CDROMBoot: cdromBoot,
			}

			err := client.Domain().CreateDomain(context.Background(), connectionID, req)
			if err != nil {
				return fmt.Errorf("创建虚拟机失败: %w", err)
			}

			fmt.Printf("✅ 虚拟机 %s 创建成功\n", args[0])

			// 显示创建信息
			if cdromPath != "" {
				fmt.Printf("   CDROM: %s\n", cdromPath)
				if cdromBoot {
					fmt.Printf("   启动顺序: CDROM 优先\n")
				}
			}

			return nil
		},
	}

	// 基础配置
	cmd.Flags().UintVarP(&vcpus, "vcpus", "", 2, "vCPU 数量")
	cmd.Flags().Uint64VarP(&memory, "memory", "m", 2048, "内存大小 (MB)")
	cmd.Flags().StringVarP(&diskPath, "disk-path", "d", "", "磁盘镜像路径 (必需)")
	cmd.Flags().StringVar(&diskBus, "disk-bus", "virtio", "磁盘总线类型 (virtio, sata, scsi)")
	cmd.Flags().StringVar(&architecture, "architecture", "x86_64", "CPU 架构 (x86_64, aarch64)")
	cmd.Flags().StringVar(&bootMode, "boot-mode", "bios", "启动模式 (bios, uefi)")
	cmd.Flags().StringVar(&networkMode, "network-mode", "network", "网络模式 (network, bridge, user)")
	cmd.Flags().StringVar(&networkName, "network-name", "default", "网络名称")
	cmd.Flags().StringVar(&osVariant, "os-variant", "", "操作系统变体 (libosinfo ID)")
	cmd.Flags().BoolVar(&autoStart, "auto-start", false, "创建后自动启动")
	cmd.Flags().BoolVar(&secureBoot, "secure-boot", false, "启用 UEFI 安全启动")

	// CDROM 配置
	cmd.Flags().StringVar(&cdromPath, "cdrom-path", "", "CDROM ISO 镜像路径")
	cmd.Flags().StringVar(&cdromBus, "cdrom-bus", "", "CDROM 总线类型 (ide, sata, scsi, virtio)")
	cmd.Flags().BoolVar(&cdromBoot, "cdrom-boot", false, "从 CDROM 启动")

	cmd.Flags().StringVarP(&connectionID, "connection", "c", "", "连接 ID")

	// 标记必需参数
	if err := cmd.MarkFlagRequired("disk-path"); err != nil {
		// 记录错误但继续执行
		fmt.Printf("Warning: Failed to mark disk-path as required: %v", err)
	}

	return cmd
}

func newDomainDeleteCommand() *cobra.Command {
	var connectionID string

	cmd := &cobra.Command{
		Use:   "delete [name]",
		Short: "删除虚拟机",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			client := ClientManager.GetClient(cmd.Flag("server").Value.String())

			err := client.Domain().DeleteDomain(context.Background(), connectionID, args[0])
			if err != nil {
				return fmt.Errorf("删除虚拟机失败: %w", err)
			}

			fmt.Printf("✅ 虚拟机 %s 删除成功\n", args[0])
			return nil
		},
	}

	cmd.Flags().StringVarP(&connectionID, "connection", "c", "", "连接 ID")
	return cmd
}

func newDomainStartCommand() *cobra.Command {
	var connectionID string

	cmd := &cobra.Command{
		Use:   "start [name]",
		Short: "启动虚拟机",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			client := ClientManager.GetClient(cmd.Flag("server").Value.String())

			err := client.Domain().StartDomain(context.Background(), connectionID, args[0])
			if err != nil {
				return fmt.Errorf("启动虚拟机失败: %w", err)
			}

			fmt.Printf("✅ 虚拟机 %s 启动成功\n", args[0])
			return nil
		},
	}

	cmd.Flags().StringVarP(&connectionID, "connection", "c", "", "连接 ID")
	return cmd
}

func newDomainShutdownCommand() *cobra.Command {
	var connectionID string

	cmd := &cobra.Command{
		Use:   "shutdown [name]",
		Short: "关闭虚拟机",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			client := ClientManager.GetClient(cmd.Flag("server").Value.String())

			err := client.Domain().ShutdownDomain(context.Background(), connectionID, args[0])
			if err != nil {
				return fmt.Errorf("关闭虚拟机失败: %w", err)
			}

			fmt.Printf("✅ 虚拟机 %s 关闭成功\n", args[0])
			return nil
		},
	}

	cmd.Flags().StringVarP(&connectionID, "connection", "c", "", "连接 ID")
	return cmd
}

func newDomainRebootCommand() *cobra.Command {
	var connectionID string

	cmd := &cobra.Command{
		Use:   "reboot [name]",
		Short: "重启虚拟机",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			client := ClientManager.GetClient(cmd.Flag("server").Value.String())

			err := client.Domain().RebootDomain(context.Background(), connectionID, args[0])
			if err != nil {
				return fmt.Errorf("重启虚拟机失败: %w", err)
			}

			fmt.Printf("✅ 虚拟机 %s 重启成功\n", args[0])
			return nil
		},
	}

	cmd.Flags().StringVarP(&connectionID, "connection", "c", "", "连接 ID")
	return cmd
}

func newDomainForceStopCommand() *cobra.Command {
	var connectionID string

	cmd := &cobra.Command{
		Use:   "force-stop [name]",
		Short: "强制停止虚拟机",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			client := ClientManager.GetClient(cmd.Flag("server").Value.String())

			err := client.Domain().ForceStopDomain(context.Background(), connectionID, args[0])
			if err != nil {
				return fmt.Errorf("强制停止虚拟机失败: %w", err)
			}

			fmt.Printf("✅ 虚拟机 %s 强制停止成功\n", args[0])
			return nil
		},
	}

	cmd.Flags().StringVarP(&connectionID, "connection", "c", "", "连接 ID")
	return cmd
}

func newDomainSuspendCommand() *cobra.Command {
	var connectionID string

	cmd := &cobra.Command{
		Use:   "suspend [name]",
		Short: "暂停虚拟机",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			client := ClientManager.GetClient(cmd.Flag("server").Value.String())

			err := client.Domain().SuspendDomain(context.Background(), connectionID, args[0])
			if err != nil {
				return fmt.Errorf("暂停虚拟机失败: %w", err)
			}

			fmt.Printf("✅ 虚拟机 %s 暂停成功\n", args[0])
			return nil
		},
	}

	cmd.Flags().StringVarP(&connectionID, "connection", "c", "", "连接 ID")
	return cmd
}

func newDomainResumeCommand() *cobra.Command {
	var connectionID string

	cmd := &cobra.Command{
		Use:   "resume [name]",
		Short: "恢复虚拟机",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			client := ClientManager.GetClient(cmd.Flag("server").Value.String())

			err := client.Domain().ResumeDomain(context.Background(), connectionID, args[0])
			if err != nil {
				return fmt.Errorf("恢复虚拟机失败: %w", err)
			}

			fmt.Printf("✅ 虚拟机 %s 恢复成功\n", args[0])
			return nil
		},
	}

	cmd.Flags().StringVarP(&connectionID, "connection", "c", "", "连接 ID")
	return cmd
}

func newDomainVCPUsCommand() *cobra.Command {
	var connectionID string

	cmd := &cobra.Command{
		Use:   "vcpus [name] [count]",
		Short: "设置虚拟机 vCPU 数量",
		Args:  cobra.ExactArgs(2),
		RunE: func(cmd *cobra.Command, args []string) error {
			client := ClientManager.GetClient(cmd.Flag("server").Value.String())

			vcpus, err := strconv.ParseUint(args[1], 10, 32)
			if err != nil {
				return fmt.Errorf("无效的 vCPU 数量: %w", err)
			}

			err = client.Domain().SetVCPUs(context.Background(), connectionID, args[0], uint(vcpus))
			if err != nil {
				return fmt.Errorf("设置 vCPU 数量失败: %w", err)
			}

			fmt.Printf("✅ 虚拟机 %s vCPU 数量设置为 %s\n", args[0], args[1])
			return nil
		},
	}

	cmd.Flags().StringVarP(&connectionID, "connection", "c", "", "连接 ID")
	return cmd
}

func newDomainMemoryCommand() *cobra.Command {
	var connectionID string

	cmd := &cobra.Command{
		Use:   "memory [name] [size]",
		Short: "设置虚拟机内存大小",
		Args:  cobra.ExactArgs(2),
		RunE: func(cmd *cobra.Command, args []string) error {
			client := ClientManager.GetClient(cmd.Flag("server").Value.String())

			memory, err := strconv.ParseUint(args[1], 10, 64)
			if err != nil {
				return fmt.Errorf("无效的内存大小: %w", err)
			}

			err = client.Domain().SetMemory(context.Background(), connectionID, args[0], memory)
			if err != nil {
				return fmt.Errorf("设置内存大小失败: %w", err)
			}

			fmt.Printf("✅ 虚拟机 %s 内存大小设置为 %s MB\n", args[0], args[1])
			return nil
		},
	}

	cmd.Flags().StringVarP(&connectionID, "connection", "c", "", "连接 ID")
	return cmd
}

func newDomainXMLCommand() *cobra.Command {
	var connectionID string

	cmd := &cobra.Command{
		Use:   "xml [name]",
		Short: "获取虚拟机 XML 配置",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			client := ClientManager.GetClient(cmd.Flag("server").Value.String())

			xml, err := client.Domain().GetDomainXML(context.Background(), connectionID, args[0])
			if err != nil {
				return fmt.Errorf("获取 XML 配置失败: %w", err)
			}

			fmt.Println(xml)
			return nil
		},
	}

	cmd.Flags().StringVarP(&connectionID, "connection", "c", "", "连接 ID")
	return cmd
}

func newDomainStatsCommand() *cobra.Command {
	var (
		outputFormat string
		connectionID string
	)

	cmd := &cobra.Command{
		Use:   "stats [name]",
		Short: "获取虚拟机统计信息",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			client := ClientManager.GetClient(cmd.Flag("server").Value.String())

			var stats map[string]interface{}
			var err error
			stats, err = client.Domain().GetDomainStats(context.Background(), connectionID, args[0])
			if err != nil {
				return fmt.Errorf("获取统计信息失败: %w", err)
			}

			return printOutput(stats, outputFormat)
		},
	}

	cmd.Flags().StringVarP(&outputFormat, "output", "o", "table", "输出格式 (table, json, yaml)")
	cmd.Flags().StringVarP(&connectionID, "connection", "c", "", "连接 ID")
	return cmd
}

func newDomainStatusCommand() *cobra.Command {
	var (
		outputFormat string
		connectionID string
	)

	cmd := &cobra.Command{
		Use:   "status [name]",
		Short: "获取虚拟机状态",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			client := ClientManager.GetClient(cmd.Flag("server").Value.String())

			var status map[string]interface{}
			var err error
			status, err = client.Domain().GetDomainStatus(context.Background(), connectionID, args[0])
			if err != nil {
				return fmt.Errorf("获取状态信息失败: %w", err)
			}

			return printOutput(status, outputFormat)
		},
	}

	cmd.Flags().StringVarP(&outputFormat, "output", "o", "table", "输出格式 (table, json, yaml)")
	cmd.Flags().StringVarP(&connectionID, "connection", "c", "", "连接 ID")
	return cmd
}
